﻿using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using System.Collections.ObjectModel;
using AzukiMap.Layer;
using AzukiMap.MapSource;
using AzukiMap.Tools.Logger;
using AzukiMap.Tools.Alert;
using System.Windows.Media.Imaging;

namespace AzukiMapUI
{
    public delegate void LayerSettingPressedHandler(object sender, ILayer selectedLayer);
    public delegate void RemoveLayerPressedHandler(object sender, ILayer selectedLayer);
    public delegate void AddLayerPressedHandler(object sender);

	public partial class LayerControl : UserControl
    {
        public event LayerSettingPressedHandler LayerSettingPressed;
        public event AddLayerPressedHandler AddLayerPressed;
        public event RemoveLayerPressedHandler RemoveLayerPressed;

        protected virtual void OnLayerSettingPressed()
        {
            if (LayerSettingPressed != null)
            {
                //LayerSettingPressed(this, _selectedLayer);
            }
        }

        protected virtual void OnAddLayerPressed()
        {
            if (AddLayerPressed != null)
            {
                AddLayerPressed(this);
            }
        }

        protected virtual void OnRemoveLayerPressed()
        {
            if (RemoveLayerPressed != null)
            {
                RemoveLayerPressed(this, _selectedLayer);
            }
        }

        #region const
        const double SELECTOR_MARGIN = 50;
        #endregion

        #region fields 
        ObservableCollection<ILayer> _layers;
        ILayer _selectedLayer;
        int _selectedIndex;
        string[] _layerTypeIcon;
        DialogOpener _dialogOpener;
        # endregion

        # region properties

        public ObservableCollection<ILayer> Layers
        {
            get { return _layers; }
            set { 
                _layers = value;
                SetLayerList();
            }
        }
        #endregion        

        #region constructor

        public LayerControl()
        {
            InitializeComponent();

            _layerTypeIcon = new string[128];
            _dialogOpener = new DialogOpener();
            SetIconSrc();
        }

        #endregion

        # region methods

        void SetLayerList()
        {
            SetLayerIcons();
            try
            {
                LbLayerList.ItemsSource = _layers;
            }
            catch (Exception ex)
            {
                Logger.Error("Failed to add layer items to the layer list.");
            }
        }

        void SetLayerIcons()
        {
            foreach (ILayer layer in _layers)
            {
                layer.DataTypeIcon = GetLayerIcon(layer);
            }
        }

        BitmapImage GetLayerIcon(ILayer layer)
        {
            BitmapImage iconImage;
            switch (layer.Type)
            {
                case MapSourceTypes.Raster:
                    iconImage = CreateBitmapFromUriString("icons/map.png");
                    break;
                case MapSourceTypes.Tile:
                    iconImage = CreateBitmapFromUriString("icons/color_swatch.png");
                    break;
                case MapSourceTypes.LayerGroup:
                    iconImage = CreateBitmapFromUriString("icons/pictures.png");
                    break;
                case MapSourceTypes.Vector:
                    iconImage = GetVectorLayerIcon((VectorLayer)layer);
                    break;
                default:
                    iconImage = CreateBitmapFromUriString("icons/chart_line.png");
                    break;
            }
            return iconImage;
        }

        BitmapImage GetVectorLayerIcon(VectorLayer layer)
        {
            BitmapImage iconImage;
            switch (layer.VectorType)
            {
                case VectorSourceTypes.Point:
                    iconImage = CreateBitmapFromUriString("icons/bullet_purple.png");
                    break;
                case VectorSourceTypes.MultiPoint:
                    iconImage = CreateBitmapFromUriString("icons/bullet_purple.png");
                    break;
                case VectorSourceTypes.LineString:
                    iconImage = CreateBitmapFromUriString("icons/chart_line.png");
                    break;
                case VectorSourceTypes.MultiLineString:
                    iconImage = CreateBitmapFromUriString("icons/chart_line.png");
                    break;
                case VectorSourceTypes.Polygon:
                    iconImage = CreateBitmapFromUriString("icons/shape_ungroup.png");
                    break;
                case VectorSourceTypes.MultiPolygon:
                    iconImage = CreateBitmapFromUriString("icons/shape_ungroup.png");
                    break;
                case VectorSourceTypes.GeometryCollection:
                    iconImage = CreateBitmapFromUriString("icons/pictures.png");
                    break;
                default:
                    iconImage = CreateBitmapFromUriString("icons/bullet_purple.png");
                    break;
            }
            return iconImage;
        }

        BitmapImage CreateBitmapFromUriString(string iconUri)
        {
             return new BitmapImage(new Uri(iconUri, UriKind.Relative));
        }

        void OpenLayerExpressionDialog()
        {
            if (_selectedLayer == null)
            {
                return;
            }
            LayerExpressionDialog dialog = new LayerExpressionDialog(_selectedLayer);
            _dialogOpener.OpenDialog(dialog);
        }

        #endregion

        # region handler

        private void BtnLayerUp_Click(object sender, RoutedEventArgs e)
        {
            if (_selectedLayer == null)
            {
                return;
            }
            MoveSelectedLayer(-1);
        }

        private void BtnLayerDown_Click(object sender, RoutedEventArgs e)
        {
            if (_selectedLayer == null)
            {
                return;
            }
            MoveSelectedLayer(1);
        }

        private void BtnLayerConfig_Click(object sender, RoutedEventArgs e)
        {
            if (_selectedLayer == null)
            {
                return;
            }
            //OnLayerSettingPressed();
            OpenLayerExpressionDialog();
        }

        private void BtnLayerAdd_Click(object sender, RoutedEventArgs e)
        {
            OnAddLayerPressed();
        }

        private void BtnLayerRemove_Click(object sender, RoutedEventArgs e)
        {
            OnRemoveLayerPressed();
        }

        private void CheckBox_Checked(object sender, RoutedEventArgs e)
        {
            FrameworkElement checkbox = (FrameworkElement)sender;
            if ( checkbox.DataContext != null)
            {
                ILayer layer = (ILayer)checkbox.DataContext;
                layer.Visiblity = Visibility.Visible;
            }
        }

        private void CheckBox_Unchecked(object sender, RoutedEventArgs e)
        {
            FrameworkElement checkbox = (FrameworkElement)sender;
            if ( checkbox.DataContext != null)
            {
                ILayer layer = (ILayer)checkbox.DataContext;
                layer.Visiblity = Visibility.Collapsed;
            }
        }

        void LayoutRoot_KeyDown(object sender, KeyEventArgs e)
        {
            if (e.Key == Key.Down)
            {
                Debug.WriteLine("Layer Down");
            }
        }

        void LbLayerList_SelectionChanged(object sender, SelectionChangedEventArgs e)
        {
            _selectedLayer = (ILayer)((ListBox)sender).SelectedItem;
            _selectedIndex = ((ListBox)sender).SelectedIndex;
            
        }

        #endregion

        void MoveSelectedLayer(int numOfMove)
        {
            int layerCount = LbLayerList.Items.Count;

            // _selectedIndex and _selectedLayer will be null when it's removed once from _layers.
            int currentIndex = _selectedIndex;
            ILayer currentLayer = _selectedLayer;
            int newIndex = currentIndex + numOfMove;

            if ( newIndex < layerCount && newIndex >= 0)
            {
                _layers.Remove(currentLayer);
                _layers.Insert(newIndex, currentLayer);
                LbLayerList.SelectedIndex = newIndex;
                currentLayer.ZIndex = newIndex;
                ResetZIndex();
            }
        }

        void ResetZIndex()
        {
            int zindex = LbLayerList.Items.Count;

            foreach (ILayer layer in _layers)
            {
                layer.ZIndex = zindex;
                zindex--;
            }
        }

        void SetIconSrc()
        {
            /*
            _layerTypeIcon[(int)MapSourceTypes.Point] = "icons/bullet_purple.png";
            _layerTypeIcon[(int)MapSourceTypes.Polygon] = "icons/shape_handles.png";
            _layerTypeIcon[(int)MapSourceTypes.MultiPolygon] = "icons/shape_ungroup.png";   // not so good
            _layerTypeIcon[(int)MapSourceTypes.MultiPoint] = "icons/bullet_purple.png";
            _layerTypeIcon[(int)MapSourceTypes.MultiLineString] = "icons/chart_line.png";
            _layerTypeIcon[(int)MapSourceTypes.LineString] = "icons/vector.png";          // not so good
            _layerTypeIcon[(int)MapSourceTypes.Raster] = "icons/cog.png";             // not yet
            _layerTypeIcon[(int)MapSourceTypes.GeometryCollection] = "icons/cog.png";             // not yet
            _layerTypeIcon[(int)MapSourceTypes.Tile] = "icons/cog.png";              // not yet
             */
        }

        #region dep
        public static readonly DependencyProperty AddLayerPressedProperty =
            DependencyProperty.Register(
                "AddLayerPressed",
                typeof(AddLayerPressedHandler),
                typeof(LayerControl),
                null);

        #endregion

    }

    public class LayerControlItems
    {
        public string Name { get; set; }
        public bool IsVisible { get; set; }
        public string DataTypeIcon { get; set; }
        string[] layerTypeIcon { get; set; }

    }


}